import { Icon, Stroke, Style } from 'ol/style';
import { LineString, Point } from 'ol/geom';
import { Feature } from 'ol';
import { fromLonLat } from 'ol/proj';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';

import mission_end_icon from '@/assets/mission_end.png';
import mission_start_icon from '@/assets/mission_start.png';
import point_svg from '@/assets/icons/point.png';

import { api } from '@/api';


const point_style = new Style({
	image: new Icon({
		anchor: [0.5, 0.5],
		src: point_svg,
	}),
});

const line_style = new Style({
	stroke: new Stroke({ color: '#ffff00', width: 2 }),
});


export class GraphLayer {
	node_source: VectorSource<Feature<Point>>;
	edge_source: VectorSource<Feature<LineString>>;
	node_layer: VectorLayer<Feature<Point>>;
	edge_layer: VectorLayer<Feature<LineString>>;
	mission_start_feature: Feature<Point>;
	mission_end_feature: Feature<Point>;


	constructor() {
		this.node_source = new VectorSource<Feature<Point>>({
			features: []
		});

		this.node_layer = new VectorLayer({
			source: this.node_source,
			style: point_style
		});

		this.edge_source = new VectorSource<Feature<LineString>>({
			features: []
		});

		this.edge_layer = new VectorLayer({
			source: this.edge_source,
			style: line_style
		});

		this.mission_start_feature = new Feature({
			geometry: new Point([0, 0]),
		});

		this.mission_end_feature = new Feature({
			geometry: new Point([0, 0]),
		});

		this.node_source.addFeature(this.mission_start_feature);
		this.node_source.addFeature(this.mission_end_feature);

		this.clearPoints();

		api.getGraph().then(response => {
			response.graph.nodes.forEach(point => {
				this.node_source.addFeature(new Feature({
					geometry: new Point(fromLonLat([point.lon, point.lat])),
				}));
			});

			response.graph.edges.forEach(edge => {
				const polygon_points: number[][] = [];

				const start_point = response.graph.nodes[edge.start_node_idx];
				const end_point = response.graph.nodes[edge.end_node_idx];

				if (start_point.lon < 0) {
					start_point.lon += 360;
				}

				if (end_point.lon < 0) {
					end_point.lon += 360;
				}

				polygon_points.push([start_point.lon, start_point.lat]);
				polygon_points.push([end_point.lon, end_point.lat]);

				const feature = new Feature({
					geometry: new LineString(polygon_points.map(p => fromLonLat(p)))
				});

				this.edge_source.addFeature(feature);
			});
		});
	}


	placePoints(start: number[], end: number[]) {
		this.mission_start_feature.setStyle(new Style({
			image: new Icon({
				anchor: [0.5, 0.5],
				src: mission_start_icon,
			}),
			zIndex: 9999
		}));

		this.mission_end_feature.setStyle(new Style({
			image: new Icon({
				anchor: [0.5, 0.5],
				src: mission_end_icon,
			}),
			zIndex: 9999
		}));

		this.mission_start_feature.getGeometry()?.setCoordinates(fromLonLat(start));
		this.mission_end_feature.getGeometry()?.setCoordinates(fromLonLat(end));
	}


	clearPoints() {
		this.mission_start_feature.setStyle(new Style({}));
		this.mission_end_feature.setStyle(new Style({}));
	}
}